package org.sixtynine.stock.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import org.apache.log4j.Logger;

public final class DateUtil {

	private static Logger logger = Logger.getLogger(DateUtil.class);

	private DateUtil() {
	}

	/** date format for db */
	public static final String DB_DATE_FORMAT = "yyyy-MM-dd";

	public static final double TIME_FOR_DAY = 1000 * 60 * 60 * 24;
	public static final String TIME_SEPERATOR = ":";

	private static final String DISPLAY_DATE_FORMAT = "dd/MM/yyyy";
	private static final String EXCEL_DATE_FORMAT = "yyyy-mm-dd";

	/** 09/05/14 02:29:58 */
	public static final String API_TIME_FORMAT = "dd/MM/yy hh:mm:ss";

	/**
	 * @param year
	 * @param month
	 * @param date
	 * @return the date
	 */
	public static Date getDate(int year, int month, int date) {
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.YEAR, year);
		calendar.set(Calendar.MONTH, (month - 1));
		calendar.set(Calendar.DATE, date);

		return calendar.getTime();
	}

	/**
	 * @return the minute of the day
	 */
	public static int getMinuteOfDay() {
		Calendar cal = Calendar.getInstance();
		return (cal.get(Calendar.HOUR_OF_DAY) * 60) + cal.get(Calendar.MINUTE);
	}

	/**
	 * @param date
	 * @return the date as standard string
	 */
	public static String getDisplayDate(Date date) {
		return getDisplayDate(date, DISPLAY_DATE_FORMAT);
	}

	/**
	 * @param date
	 * @param dateFormat
	 * @return the date in given string format
	 */
	public static String getDisplayDate(Date date, String dateFormat) {
		SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
		return sdf.format(date);
	}

	/**
	 * @param fromDate
	 * @param toDate
	 * @return the difference in days between 2 given days
	 */
	public static int getDifference(Date fromDate, Date toDate) {
		return (int) (Math.rint(toDate.getTime() - fromDate.getTime()) / TIME_FOR_DAY);
	}

	/**
	 * @param date
	 * @param calType
	 * @param amount
	 * @return the new date
	 */
	public static Date add(Date date, int calType, int amount) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(calType, amount);

		return calendar.getTime();
	}

	/**
	 * @param date
	 * @return the date for the given string
	 * @throws ParseException
	 */
	public static Date getDate(String date) throws ParseException {
		return getDate(DISPLAY_DATE_FORMAT, date);
	}

	/**
	 * @param date
	 * @return the date for the given string
	 * @throws ParseException
	 */
	public static Date getExcelDate(String date) throws ParseException {
		return getDate(EXCEL_DATE_FORMAT, date);
	}

	/**
	 * @param date
	 * @return the date for the given string
	 * @throws ParseException
	 */
	public static Date getApiDate(String date) throws ParseException {
		return getDate(API_TIME_FORMAT, date);
	}

	/**
	 * @param dateFormat
	 * @param date
	 * @return the date from the given string
	 * @throws ParseException
	 */
	public static Date getDate(String dateFormat, String date)
			throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
		return sdf.parse(date);
	}

	/**
	 * @param fileName
	 * @return the date in the given format
	 */
	public static Date getFormattedDate(String fileName) {
		Date date = null;
		String dteArry[] = fileName.split("_", 2);
		String dateS = dteArry[0];

		String finalDate = dateS.substring(4, 8) + "-" + dateS.substring(2, 4)
				+ "-" + dateS.substring(0, 2);
		SimpleDateFormat dt = new SimpleDateFormat(DB_DATE_FORMAT);
		try {
			date = dt.parse(finalDate);
		} catch (ParseException e) {
			logger.error(e.getCause());
		}

		return date;
	}

	/**
	 * @param date
	 * @return true if the date is the last date of the month, false otherwise
	 */
	public static boolean isLastDateOfMonth(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		if (cal.get(Calendar.DATE) == cal
				.getActualMaximum(Calendar.DAY_OF_MONTH)) {
			return true;
		}

		return false;
	}

	public static String getQuearterCode(int year, String quarterCode) {
		if (year > 0) {
			return quarterCode + year;
		}
		return quarterCode;
	}

	/**
	 * Checks if two date objects are on the same day ignoring time.
	 * 
	 * 28 Mar 2002 13:45 and 28 Mar 2002 06:01 would return true. 28 Mar 2002
	 * 13:45 and 12 Mar 2002 13:45 would return false.
	 * 
	 * 
	 * @param date1
	 *            the first date, not altered, not null
	 * @param date2
	 *            the second date, not altered, not null
	 * @return true if they represent the same day
	 * @throws IllegalArgumentException
	 *             if either date is <code>null</code>
	 * @since 2.1
	 */
	public static boolean isSameDay(Date date1, Date date2) {
		if (date1 == null || date2 == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		Calendar cal1 = Calendar.getInstance();
		cal1.setTime(date1);
		Calendar cal2 = Calendar.getInstance();
		cal2.setTime(date2);
		return isSameDay(cal1, cal2);
	}

	/**
	 * Checks if two calendar objects are on the same day ignoring time.
	 * 
	 * 28 Mar 2002 13:45 and 28 Mar 2002 06:01 would return true. 28 Mar 2002
	 * 13:45 and 12 Mar 2002 13:45 would return false.
	 * 
	 * 
	 * @param cal1
	 *            the first calendar, not altered, not null
	 * @param cal2
	 *            the second calendar, not altered, not null
	 * @return true if they represent the same day
	 * @throws IllegalArgumentException
	 *             if either calendar is <code>null</code>
	 * @since 2.1
	 */
	public static boolean isSameDay(Calendar cal1, Calendar cal2) {
		if (cal1 == null || cal2 == null) {
			throw new IllegalArgumentException("The date must not be null");
		}
		return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA)
				&& cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && cal1
					.get(Calendar.DAY_OF_YEAR) == cal2
				.get(Calendar.DAY_OF_YEAR));
	}

	public static int getYearFromDate(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.get(Calendar.YEAR);
	}

	public static int getMonthFromDate(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.get(Calendar.MONTH);

	}

	public static int getDateFromDate(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.get(Calendar.DATE);
	}

	public static boolean checkWeeklyFinalDate(Date date) {
		boolean result = false;
		if (date != null) {

			int processMonth = getMonthFromDate(date);
			int processYear = getYearFromDate(date);
			int processDate = getDateFromDate(date);

			// System.out.println(Calendar.DAY_OF_WEEK);

			Calendar cal = Calendar.getInstance();
			cal.set(Calendar.YEAR, processYear);
			cal.set(Calendar.MONTH, processMonth);
			cal.set(1, cal.getActualMaximum(1));

			Date finalDate = cal.getTime();
			result = (processDate == getDateFromDate(finalDate));
		}
		return result;
	}

	public static boolean checkMonthlyFinalDate(Date date) {
		boolean result = false;
		if (date != null) {

			int processMonth = getMonthFromDate(date);
			int processYear = getYearFromDate(date);

			Calendar cal = Calendar.getInstance();
			if (processYear == cal.YEAR && processMonth == cal.MONTH) {
				result = true;
			}
		}
		return result;
	}

	public static boolean checkFutureDate(Date date) {
		boolean result = false;
		if (date != null) {
			Date todayDate = new Date();
			result = (todayDate.compareTo(date) < 0);
		}
		return result;
	}

	public static Date getMonthStart(int month) {
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.MONTH, month);
		calendar.set(Calendar.DATE, 1);

		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	public static Date getMonthEnd(int month) {
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.MONTH, month);
		calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	public static Date getWeekStart(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK) - cal.getFirstDayOfWeek();
		cal.add(Calendar.DAY_OF_MONTH, -dayOfWeek);

		return cal.getTime();
	}

	public static Date getWeekEnd(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);

		int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK) - cal.getFirstDayOfWeek();
		cal.add(Calendar.DAY_OF_MONTH, -dayOfWeek);
		cal.add(Calendar.DAY_OF_MONTH, 6);

		return cal.getTime();
	}

	public static Date getYearStart(Date date) {
		Calendar calendar = Calendar.getInstance();

		calendar.set(Calendar.YEAR, getYearFromDate(date));
		calendar.set(Calendar.MONTH, 0);
		calendar.set(Calendar.DAY_OF_MONTH, 1);

		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	public static Date getYearEnd(Date date) {
		Calendar calendar = Calendar.getInstance();

		calendar.set(Calendar.YEAR, getYearFromDate(date));
		calendar.set(Calendar.MONTH, 11);
		calendar.set(Calendar.DAY_OF_MONTH, 31);

		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	public static Date getNextPaidDate(int month, Date date) {
		Calendar calendar = Calendar.getInstance();
		int newYear = getYearFromDate(date) + 1;
		int newDate = getDateFromDate(date);
		calendar.set(Calendar.YEAR, newYear);
		calendar.set(Calendar.MONTH, (month - 1));
		calendar.set(Calendar.DAY_OF_MONTH, newDate);

		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	public static Date getBeforeDate(Date date) {
		Calendar calendar = Calendar.getInstance();

		calendar.set(Calendar.YEAR, getYearFromDate(date));
		calendar.set(Calendar.MONTH, getMonthFromDate(date));
		calendar.set(Calendar.DAY_OF_MONTH, (getDateFromDate(date) - 1));

		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	/**
	 * this use to list process check exists data
	 * 
	 * @param date
	 * @return
	 */
	public static String getDataString(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);

		return (calendar.get(Calendar.YEAR) + "_"
				+ (calendar.get(Calendar.MONTH) + 1 )+ "_" + calendar
					.get(Calendar.DATE));
	}

}
